#include "kernel.h"

#if 0

/* ret: 0 for success, negative for failed */
static void
sc_fork_mem(struct trapframe_t *tf)
{
	 tf->regs.eax = fork_mem();
}

/* arg0(ebx): virtual address, UVPT area means the 4M dir entry */
/* ret: negative for failed */
static void
sc_alloc_temp(struct trapframe_t *tf)
{
	 uintptr_t addr = tf->regs.ebx;
	 if (addr > UWLIM)
	 {
		  if (UVPT <= addr && addr < ULIM)
		  {
			   int idx = PAGETAB_IDX(addr);
			   tf->regs.eax = vpd_alloc_temp(idx);
		  }
		  else tf->regs.eax = -E_INVAL;
	 }
	 else
	 {
		  tf->regs.eax = vpt_alloc_temp(PAGE_NUM(addr));
	 }
}

/* arg0(ebx): the num of page */
/* ret: the physaddr of page, 0 for failed */
static void
sc_alloc_io(struct trapframe_t *tf)
{
	 int num = tf->regs.ebx;
	 physaddr_t result;
	 if (pmem_page_alloc(num, &result) < 0)
		  tf->regs.eax = 0;
	 else tf->regs.eax = result;
}

/* arg0(ebx): virtual address, UVPT area means the 4M dir entry */
/* ret: negative for failed */
static void
sc_mark_shared(struct trapframe_t *tf)
{
	 uintptr_t addr = tf->regs.ebx;
	 if (addr > UWLIM)
	 {
		  if (UVPT <= addr && addr < ULIM)
		  {
			   int idx = PAGETAB_IDX(addr);
			   tf->regs.eax = vpd_mark_shared(idx);
		  }
		  else tf->regs.eax = -E_INVAL;
	 }
	 else
	 {
		  tf->regs.eax = vpt_mark_shared(PAGE_NUM(addr));
	 }
}

/* arg0(ebx): vaddr of format */
/* arg1(ecx): vaddr of va_list */
static void
sc_kprintf(struct trapframe_t *tf)
{
     const char *fmt = (const char *)tf->regs.ebx;
     va_list va = (va_list)tf->regs.ecx;

     vkprintf(fmt, va);
}

/* arg0(ebx): new priority, < 0 or >= PRIORITY_COUNT means not change*/
/* ret: negative for failed, or returns the old priority */
static void
sc_set_priority(struct trapframe_t *tf)
{
	 int pri = tf->regs.ebx;
	 tf->regs.eax = procs[cur_proc_id()].priority;
	 if (pri >= 0 && pri < PRIORITY_COUNT)
	 {
		  if ((pri = proc_set_priority(pri))
			  < 0)
			   tf->regs.eax = pri;
	 }
}

/* arg0(ebx): the code pointer of the handler */
/* ret: negative for failed, or success */
static void
sc_set_sh(struct trapframe_t *tf)
{
	 uintptr_t sh = tf->regs.ebx;
	 tf->regs.eax = proc_set_signal_handler(sh);
}

/* arg0(ebx): the new flags */
/* arg1(ecx): the sch signal count, 0 for not change */
/* ret: negative for failed, or success */
static void
sc_set_sf(struct trapframe_t *tf)
{
	 uint16_t flags = tf->regs.ebx;
	 uint16_t count = tf->regs.ecx;
	 tf->regs.eax = proc_set_signal_flags(flags, count);
}

/* arg0(ebx): the address of spinlock */
/* ret: negative for failed */
static void
sc_spl_acquire(struct trapframe_t *tf)
{
	 spin_lock_t *lock = (spin_lock_t *)tf->regs.ebx;
	 if (tf->regs.ebx >= UWLIM)
		  tf->regs.eax = -E_INVAL;
	 else
	 {
		  while (xchg32(lock, 1) == 1)
			   call_yield();
		  tf->regs.eax = 0;
	 }
}

/* arg0(ebx): the address of spin_lock */
/* ret: negative for failed */
static void
sc_wait(struct trapframe_t *tf)
{
	 tf->regs.eax = sch_wait(cur_proc_id(),
							 1,
							 (spin_lock_t *)tf->regs.ebx);
	 call_yield();
}

/* arg0(ebx): the pid to notify */
/* ret: negative for failed */
static void
sc_notify(struct trapframe_t *tf)
{
	 /* TODO, modify */
	 tf->regs.eax = sch_notify((proc_id_t)tf->regs.ebx, 1);
}

static void
sc_fork_proc(struct trapframe_t *tf)
{
	 uintptr_t eip = tf->eip;
	 uintptr_t esp = tf->stk.esp;
	 
	 tf->eip = ARG1(tf);
	 tf->stk.esp = ARG2(tf)
	 tf->regs.eax = 0;
	 fork_proc(tf);
	 
	 tf->eip = eip;
	 tf->stk.esp = esp;
	 
	 if (tf->regs.eax < 0)
		  kprintf("%d fork: %e\n", cur_proc_id(), tf->regs.eax);
}

#endif
